// Package main provides ...
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strings"
)

var (
	path   string
	doType int
)

func main() {
	fmt.Println("操作功能：\n1. 在特定目录下找出特定格式文件\n2.拷贝特定文件到特定目录下\n3.统计出给定目录下某个单词出现的次数")
	fmt.Println("请输入要进行的操作")
	fmt.Scan(&doType)
	fmt.Println("请输入要检索的目录")
	fmt.Scan(&path)
	openOldFile(path, doType)

}

func openOldFile(path string, doType int) {
	//打开目录文件
	file, err := os.OpenFile(path, os.O_RDONLY, os.ModeDir)
	if err != nil {
		fmt.Println("open file faild ,err:", err)
		return
	}
	defer file.Close()
	//读取全部目录文件
	info, err := file.ReadDir(-1)
	if err != nil {
		fmt.Println("read dir faild,err:", err)
		return
	}
	switch doType {
	case 1:
		{
			var fileType string
			fmt.Println("请输入要检索的文件类型")
			fmt.Scan(&fileType)
			nams := search(path, fileType, info)
			fmt.Printf("%s 下有 %s 格式文件有：%v\n", path, fileType, nams)
		}
	case 2:

		{

			var (
				fileName   string
				targetPath string
			)
			fmt.Println("请输入要拷贝的文件")
			fmt.Scan(&fileName)
			fmt.Println("请输入要考入到的目录")
			fmt.Scan(&targetPath)
			copy(path, targetPath, fileName, info)
		}
	case 3:
		{

			var word string
			fmt.Println("请输入要检索的的单词")
			fmt.Scan(&word)
			c := count(path, word, info)
			fmt.Printf("%s 出现了%d次\n", word, c)
		}

	}

}

// 找出给定文件下  给定格式文件
func search(path, fileType string, info []os.DirEntry) (names []string) {
	//遍历目录文件
	for _, fileInfo := range info {
		//判断是否为目录
		if !fileInfo.IsDir() {
			//判断是否为 给定文件格式结尾
			if strings.HasSuffix(fileInfo.Name(), fileType) {
				names = append(names, fileInfo.Name())
			}
		}
	}
	return
}

func complatementPath(path string) string {
	if strings.HasSuffix(path, "/") {
		return path
	} else {
		path = path + "/"
		return path
	}
}

//拷贝给定文件到给定目录下
func copy(path, targetPath, fileName string, info []os.DirEntry) {
	for _, fileInfo := range info {
		if !fileInfo.IsDir() {
			if fileInfo.Name() == fileName {
				oldFile, err := os.OpenFile(complatementPath(path)+fileName, os.O_RDONLY, 6)
				if err != nil {
					fmt.Println("open old file faild,err :", err)
					return
				}
				defer oldFile.Close()
				newfile, err := os.Create(complatementPath(targetPath) + fileInfo.Name())
				if err != nil {
					fmt.Println("create new file faild,err:", err)
					return
				}
				buf := make([]byte, 4*1024)
				for {
					//读文件到缓冲区中
					n, err := oldFile.Read(buf)
					//判断文件是否读完毕
					if n == 0 {
						fmt.Println("old file read over")
						return
					}
					if err != nil {
						fmt.Println("old file read faild ,err :", err)
						return
					}
					//写文件
					newfile.Write(buf[:n])
				}
			}
			fmt.Printf("已经将%s copy 到 %s中\n", complatementPath(path)+fileName, complatementPath(targetPath)+fileName)
		}
	}
}

//统计出给定目录下某个单词出现的次数。
func count(path, word string, info []os.DirEntry) int {
	var c int
	for _, fileInfo := range info {
		if !fileInfo.IsDir() {
			file, err := os.Open(complatementPath(path) + fileInfo.Name())
			if err != nil {
				fmt.Printf("open %s faild,err:%s", complatementPath(path)+fileInfo.Name(), err)
			}
			defer file.Close()
			//创建一个带缓冲区的reader
			reader := bufio.NewReader(file)

			for {
				//按行读
				buf, err := reader.ReadBytes('\n')
				//判断是否到了文件结尾
				if err != nil && err != io.EOF {
					fmt.Println("reader readBytes faild,err:", err)
					return 0
				} else if err == io.EOF {
					fmt.Println(" file read over")
					break
				}
				//转换为字符串后统计
				bufString := string(buf)
				count := strings.Count(bufString, word)
				c = c + count
			}
		}
	}
	return c
}
